package com.jyw.business.obstacles.websocket.handler;

import com.alibaba.fastjson2.JSONObject;
import com.jyw.business.obstacles.domain.vo.web.ServerDeskWebSocketVO;
import com.jyw.business.obstacles.service.IObsLocalPhoneService;
import com.jyw.business.obstacles.utils.WebSocketUtils;
import com.jyw.business.obstacles.websocket.config.WsSessionManager;
import com.jyw.common.constant.CacheConstants;
import com.jyw.common.core.domain.model.LoginUser;
import com.jyw.common.core.redis.RedisCache;
import com.jyw.common.exception.ServiceException;
import com.jyw.common.utils.StringUtils;
import com.jyw.framework.web.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * @author 沈峻
 * @ClassName ServerDeskHandler
 * @Description 服务台Websocket处理实现
 * @Date 2023/8/21 14:37
 **/
@Component
@Slf4j
public class ServerDeskHandler extends TextWebSocketHandler {


    @Resource
    private TokenService tokenService;

    @Resource
    private RedisCache redisCache;

    @Resource
    private IObsLocalPhoneService localPhoneService;

    /**
     * socket 建立成功事件
     *
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String token = (String)session.getAttributes().get("token");
        if (token != null) {
            LoginUser loginUser = tokenService.getLoginUser(token);
            // 用户连接成功，放入在线用户缓存
            WsSessionManager.add(loginUser.getUserId(), session);
            //发送当前坐席信息
            WebSocketUtils.send(ServerDeskWebSocketVO.ofSeatCurrent(localPhoneService.getSeatCache()),loginUser.getUserId());

        } else {
            throw new RuntimeException("用户登录已经失效!");
        }
    }

    /**
     * 获取当前连接的用户id
     * @param session
     * @return
     */
    private Long getUserId(WebSocketSession session){
        String token = (String)session.getAttributes().get("token");
        if (!StringUtils.isEmpty(token)) {
            LoginUser loginUser = tokenService.getLoginUser(token);
            if(ObjectUtils.isEmpty(loginUser)){
                log.warn("token失效,ip:{},:token:{}",session.getRemoteAddress(),token);
                throw new ServiceException("用户登录已经失效!");
            }
            return loginUser.getUserId();
        } else {
            throw new RuntimeException("token不能为空!");
        }
    }

    /**
     * 接收消息事件
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 获得客户端传来的消息
        String payload = message.getPayload();
        Object token = session.getAttributes().get("token");
        try {
            JSONObject jsonMsg = JSONObject.parse(payload);
            if(jsonMsg.getInteger("code")!=15){
                log.debug("server 接收到 " + getUserId(session) + " 发送的 " + payload);
            }
            //处理信息
            handlerMessage(jsonMsg,session);
        }catch (Exception e){
            log.error("客户端发送信息解析报错:{}",payload,e);
        }
    }

    /**
     * socket 断开连接时
     *
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String token = (String)session.getAttributes().get("token");
        if (token != null) {
            LoginUser loginUser = tokenService.getLoginUser(token);
            // 用户退出，移除缓存
            if(!ObjectUtils.isEmpty(loginUser)){
                WsSessionManager.remove(loginUser.getUserId());
            }else{
                WsSessionManager.remove(session);
            }
        }
    }

    /**
     * 处理接收到的信息
     * @param message
     */
    private void handlerMessage(JSONObject message,WebSocketSession session) throws IOException {
        Long userId = getUserId(session);
        switch (message.getInteger("code")) {
            case 15:
                //心跳
                session.sendMessage(new TextMessage(ServerDeskWebSocketVO.ofHeartBeat()));
                break;
            case 16:
                //人工座席
                List<String> data = message.getJSONArray("data").toJavaList(String.class);
                log.debug("用户:{},发送坐席信息:{}",userId,data);
                Map<String, Long> cacheMap = localPhoneService.getSeatCache();
                //先将该用户的所有坐席取消
                for (String key : cacheMap.keySet()) {
                    Long uid = cacheMap.get(key);
                    if(userId.equals(uid)){
                        //当前用户已经取消该坐席
                        if (!data.contains(key)) {
                            cacheMap.put(key,null);
                        }
                    }
                    //匹配上赋值
                    if(data.contains(key)){
                        cacheMap.put(key,userId);
                    }
                }
                //重新将坐席写入缓存中
                redisCache.setCacheMap(CacheConstants.SEAT_NOW,cacheMap);
                //广播坐席
                broadSeat();
                break;
            case 18:
                //呼叫转移
                break;
            case 19:
                //微信报修订阅通知
                break;
        }
    }

    /**
     * 广播坐席变更
     */
    private void broadSeat(){
        //获取当前的坐席
        Map<String, Long> seatCache = localPhoneService.getSeatCache();
        String msg = ServerDeskWebSocketVO.ofSeatInfo(seatCache);
        WebSocketUtils.broad(msg);
    }
}
